#include <QSqlQuery>
#include "monthlywidget.h"

namespace{

    struct Task{
        int userID;
        QString userName;
        int productID;
        QString productName;
        int componentID;
        QString componentName;
        int taskID;
        QString taskName;
        bool billable;
        int clientID;
        QString clientName;
        bool operator <(const Task& other) const{
            if (userID < other.userID)
                return true;
            else if (userID == other.userID)
                if (componentID < other.componentID)
                    return true;
                else if (componentID == other.componentID)
                    if (taskID < other.taskID)
                        return true;
            return false;
        }
    };

    typedef QMap<QDate, qreal> WorkingHours;
    typedef QMap<Task, WorkingHours>  WorkingHourPerTask;
}


MonthlyWidget::MonthlyWidget(QWidget *parent) :
    QTableWidget(parent)
{
    setSortingEnabled(true);

    connect(this, SIGNAL(userIDChanged(int)), SLOT(on_userID_changed(int)));
    connect(this, SIGNAL(timeTableVisibled(bool)), SLOT(on_timeTable_visibled(bool)));
    connect(this, SIGNAL(dateChanged(QDate)), SLOT(on_date_changed(QDate)));
    connect(this, SIGNAL(dateFormatChanged(QString)), SLOT(on_dateFormat_changed(QString)));
}

void MonthlyWidget::refresh()
{
    QDateTime s = QDateTime(QDate(date_.year(), date_.month(), 1), QTime(0, 0, 0));
    QDateTime e = s.addMonths(1);

    QString q = QString(
                    "SELECT A.startTime, A.endTime, P.id, P.name, CO.id, CO.name, TC.id, TC.name, TC.billable, CY.id, CY.name"
                    " from ACTUAL AS A, PRODUCT AS P, TASKCATEGORY as TC, COMPANY AS CY, CLIENTUSERS AS CL"
                    " LEFT JOIN COMPONENT AS CO ON A.compid=CO.id"
                    " where A.prodid=P.id and A.cateid=TC.id and P.clientID=CL.id and CL.companyID=CY.id and"
                    " A.startTime>='%1' and A.endTime<='%2' and A.userid='%3'").arg(s.toString(Qt::ISODate)).arg(e.toString(Qt::ISODate)).arg(userID_);
    QSqlQuery query = db_.exec(q);

    WorkingHourPerTask hours;
    while (query.next()) {
        QDateTime s = query.value(0).toDateTime();
        QDateTime e = query.value(1).toDateTime();

        Task task;
        task.productID = query.value(2).toInt();
        task.productName = query.value(3).toString();
        task.componentID = query.value(4).toInt();
        task.componentName = query.value(5).toString();
        task.taskID = query.value(6).toInt();
        task.taskName = query.value(7).toString();
        task.billable = query.value(8).toBool();
        task.clientID = query.value(9).toInt();
        task.clientName = query.value(10).toString();
        hours[task][s.date()] += s.secsTo(e) / 60.0 / 60.0;
    }

    QStringList labels = QStringList() << tr("Product Name") << tr("Component Name") << tr("Task Name") << tr("Billable") << tr("Client Name");
    QDate date = s.date();
    while (date < e.date()) {
        labels.push_back(date.toString("dd"));
        date = date.addDays(1);
    }
    setRowCount(hours.size());
    setColumnCount(labels.size());
    setHorizontalHeaderLabels(labels);

    setColumnWidth(0, 530);
    setColumnWidth(1, 150);
    setColumnWidth(2, 120);
    setColumnWidth(3, 80);
    setColumnWidth(4, 120);
    for (int i=5; i<labels.size(); ++i)
        setColumnWidth(i, 40);

    int r = 0;
    WorkingHourPerTask::const_iterator iter = hours.begin();
    while(iter != hours.end()) {
        setItem(r, 0, new QTableWidgetItem(iter.key().productName));
        setItem(r, 1, new QTableWidgetItem(iter.key().componentName));
        setItem(r, 2, new QTableWidgetItem(iter.key().taskName));
        setItem(r, 3, new QTableWidgetItem(iter.key().billable ? "1" : "0"));
        setItem(r, 4, new QTableWidgetItem(iter.key().clientName));

        const WorkingHours& h = iter.value();
        date = s.date();
        int c = 5;
        while (date < e.date()) {
            if (h[date] > 0.0) {
                QTableWidgetItem* item = new QTableWidgetItem(QString("%1").arg(h[date], 0, 'f', 1));
                item->setTextAlignment(Qt::AlignRight);
                setItem(r, c, item);
            }

            ++c;
            date = date.addDays(1);
        }

        ++iter;
        ++r;
    }
}

void MonthlyWidget::on_userID_changed(int userID)
{
    refresh();
}

void MonthlyWidget::on_timeTable_visibled(bool visible)
{
    refresh();
}

void MonthlyWidget::on_date_changed(const QDate& date)
{
    refresh();
}

void MonthlyWidget::on_dateFormat_changed(const QString& format)
{
    refresh();
}
